interface Type {
    getName():string;
    toString():string;
}

class _Symbol {
    name:string;
    type:Type | null;

    constructor(name:string,type:Type | null = null){
        this.name = name;
        this.type = type;
    }

    getName(){
        return this.name;
    }

    toString(){
        if(this.type){
            return '<'+this.getName()+':'+this.type.toString()+'>';
        }else{
            return this.getName();
        }
    }
}

class VariableSymbol extends _Symbol {

}

class BuiltInSymbol extends _Symbol implements Type {
    toString(){
        return this.name;
    }
}

interface Scope {
    getScopeName():string;
    getEnclosingScope():Scope | null;
    // add(name,_Symbol)
    define(sym:_Symbol):void;
    // get(name)=>_Symbol
    resolve(name:string):_Symbol;
}

// 全局作用域的符号表
class SymbolTable implements Scope {
    // int IntSym
    // float FloatSym
    symbols:Map<string,_Symbol> = new Map();
    constructor(){
        this.initTypeSystem();
    }
    initTypeSystem(){
        this.define(new BuiltInSymbol('int'));
        this.define(new BuiltInSymbol('float'))
    }
    getScopeName(): string {
        return 'globals';
    }
    getEnclosingScope(): Scope | null {
        return null;
    }
    define(sym: _Symbol): void {
        this.symbols.set(sym.name,sym);
    }
    resolve(name: string): _Symbol {
        return this.symbols.get(name) as _Symbol;
    }

    toString(){
        let buf = '';
        buf += this.getScopeName() + ": {";
        this.symbols.forEach(s => {
            buf += s.name+"=" + s.toString()+","
        })
        buf += '}'
        return buf;
    }
}

export {
    SymbolTable,
    VariableSymbol
}